package com.qding.park.manager.web.log;

import java.lang.reflect.Method;
import java.util.Date;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.qding.park.common.core.annotation.log.OperationLogType;
import com.qding.park.common.core.annotation.log.SystemControllerLog;
import com.qding.park.common.core.annotation.log.SystemServiceLog;
import com.qding.park.manager.facade.statis.service.LogStatisFacade;
import com.qding.park.manager.pojo.LogInfo;
import com.qding.smart.sso.client.entry.UserInfo;
import com.qding.smart.sso.client.util.SSOClientHelp;

/**
 * @author Administrator
 *切点类 
 */
@Aspect    
@Order(Integer.MAX_VALUE)
@Component  
public class SystemLogAspect {
	
	 //注入Service用于把日志保存数据库    
    @Resource    
    private LogStatisFacade logStatisFacade;    
    //本地异常日志记录对象    
    private  static  final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);    
    
    //Service层切点    
    @Pointcut("@annotation(com.qding.park.common.core.annotation.log.SystemServiceLog)")    
     public  void serviceAspect() {    
    }    
    
    //Controller层切点    
    @Pointcut("@annotation(com.qding.park.common.core.annotation.log.SystemControllerLog)")    
     public  void controllerAspect() {    
    }    
    
    /**  
     * 前置通知 用于拦截Controller层记录用户的操作  
     *  
     * @param joinPoint 切点  
     */    
    @Before("@annotation(com.qding.park.common.core.annotation.log.SystemControllerLog)")    
     public  void doBefore(JoinPoint joinPoint) {    
    	logger.info("开始记录访问日志:{},{}",joinPoint.getTarget().getClass().getName(),joinPoint.getSignature());
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();    
        HttpSession session = request.getSession();    
        //读取session中的用户    
//        UserInfo user = (UserInfo) session.getAttribute(WebConstants.CURRENT_USER);  
        UserInfo user=SSOClientHelp.getUserInfo(request);
        if(user==null){
        	user=new UserInfo();
        	user.setUserName("匿名用户");
        }
        //请求的IP    
        String ip = request.getRemoteAddr();    
        String requestUri=request.getRequestURI();
         try {    
            //*========控制台输出=========*//    
            System.out.println("=====前置通知开始=====");    
            System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    
            System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));    
            System.out.println("请求人:" + user.getUserName());    
            System.out.println("请求IP:" + ip);    
            //*========数据库日志=========*//    
            
            String params = "";    
            if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {    
                for ( int i = 0; i < joinPoint.getArgs().length; i++) {    
               	 params += joinPoint.getArgs()[i] + ";";
               }    
           }    
            
            LogInfo log = new  LogInfo();    
            OperationLogType  operType=getControllerMethodOper(joinPoint);
            log.setUserName(user.getUserName());
            log.setDescription(getControllerMethodDescription(joinPoint));  
            log.setRequestUri(requestUri);
            log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    
            log.setType(operType.getType());    
            log.setRequestIp(ip);    
            log.setExceptionCode( null);    
            log.setExceptionDetail( null);    
            log.setParams( params);    
//           log.setCreateBy(user);    
            log.setCreateDate(new Date());    
            //保存数据库    
            logStatisFacade.save(log);    
            System.out.println("=====前置通知结束=====");    
        }  catch (Exception e) {    
            //记录本地异常日志    
            logger.error("==前置通知异常==");    
            logger.error("异常信息:{}", e.getMessage());    
        }    
    }    
    
    /**  
     * 异常通知 用于拦截service层记录异常日志  
     *  未完成
     * @param joinPoint  
     * @param e  
     */    
//    @AfterThrowing(pointcut = "serviceAspect()", throwing = "e")    
//     public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {    
//        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();    
//        HttpSession session = request.getSession();    
//        //读取session中的用户    
//        UserInfo user = (UserInfo) session.getAttribute(WebConstants.CURRENT_USER);    
//        //获取请求ip    
//        String ip = request.getRemoteAddr();    
//        //获取用户请求方法的参数并序列化为JSON格式字符串    
//        String params = "";    
//         if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {    
//             for ( int i = 0; i < joinPoint.getArgs().length; i++) {    
////                params += JSONUtil.toJsonString(joinPoint.getArgs()[i]) + ";";    
//            	 
//            	 params += joinPoint.getArgs()[i] + ";";
//            }    
//        }    
//         try {    
//              /*========控制台输出=========*/    
//            System.out.println("=====异常通知开始=====");    
//            System.out.println("异常代码:" + e.getClass().getName());    
//            System.out.println("异常信息:" + e.getMessage());    
//            System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    
//            System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));    
//            System.out.println("请求人:" + user.getName());    
//            System.out.println("请求IP:" + ip);    
//            System.out.println("请求参数:" + params);    
//               /*==========数据库日志=========*/    
//            LogInfo log = new LogInfo();    
//            OperationLogType  operType=getControllerMethodOper(joinPoint);
//            log.setDescription(getServiceMthodDescription(joinPoint));    
//            log.setExceptionCode(e.getClass().getName());    
//            log.setType(operType.getType());    
//            log.setExceptionDetail(e.getMessage());    
//            log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    
//            log.setParams(params);    
//            log.setCreateBy(user);    
//            log.setCreateDate(new Date());    
//            log.setRequestIp(ip);    
//            //保存数据库    
//            logFacade.save(log);    
//            System.out.println("=====异常通知结束=====");    
//        }  catch (Exception ex) {    
//            //记录本地异常日志    
//            logger.error("==异常通知异常==");    
//            logger.error("异常信息:{}", ex.getMessage());    
//        }    
//         /*==========记录本地异常日志==========*/    
//        logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);    
//    
//    }    
    
    
    /**  
     * 获取注解中对方法的描述信息 用于service层注解  
     *  
     * @param joinPoint 切点  
     * @return 方法描述  
     * @throws Exception  
     */    
     public  static String getServiceMthodDescription(JoinPoint joinPoint)    
             throws Exception {    
        String targetName = joinPoint.getTarget().getClass().getName();    
        String methodName = joinPoint.getSignature().getName();    
        Object[] arguments = joinPoint.getArgs();    
        Class targetClass = Class.forName(targetName);    
        Method[] methods = targetClass.getMethods();    
        String description = "";    
         for (Method method : methods) {    
             if (method.getName().equals(methodName)) {    
                Class[] clazzs = method.getParameterTypes();    
                 if (clazzs.length == arguments.length) {    
                    description = method.getAnnotation(SystemServiceLog.class).description();    
                     break;    
                }    
            }    
        }    
         return description;    
    }    
    
    /**  
     * 获取注解中对方法的描述信息 用于Controller层注解  
     *  
     * @param joinPoint 切点  
     * @return 方法描述  
     * @throws Exception  
     */    
     public  static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {    
        String targetName = joinPoint.getTarget().getClass().getName();    
        String methodName = joinPoint.getSignature().getName();    
        Object[] arguments = joinPoint.getArgs();    
        Class targetClass = Class.forName(targetName);    
        Method[] methods = targetClass.getMethods();    
        String description = "";    
         for (Method method : methods) {    
             if (method.getName().equals(methodName)) {    
                Class[] clazzs = method.getParameterTypes();    
                 if (clazzs.length == arguments.length) {    
                    description = method.getAnnotation(SystemControllerLog.class).description();    
                     break;    
                }    
            }    
        }    
         return description;    
    }
     
     public  static OperationLogType getControllerMethodOper(JoinPoint joinPoint)  throws Exception {    
         String targetName = joinPoint.getTarget().getClass().getName();    
         String methodName = joinPoint.getSignature().getName();    
         Object[] arguments = joinPoint.getArgs();    
         Class targetClass = Class.forName(targetName);    
         Method[] methods = targetClass.getMethods();    
         OperationLogType operationLogType=OperationLogType.NULL_OPER;    
          for (Method method : methods) {    
              if (method.getName().equals(methodName)) {    
                 Class[] clazzs = method.getParameterTypes();    
                  if (clazzs.length == arguments.length) {    
                	  operationLogType = method.getAnnotation(SystemControllerLog.class).operation();    
                      break;    
                 }    
             }    
         }    
          return operationLogType;    
     }
}
